package ph.com.gs3.formalistics.services.synchronizers;

import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import ph.com.gs3.formalistics.global.constants.UserUpdateOptions;
import ph.com.gs3.formalistics.model.facades.UsersDataWriter;
import ph.com.gs3.formalistics.model.ldao.UsersLDAO;
import ph.com.gs3.formalistics.model.vo.business.User;
import android.content.Context;

public class UsersSynchronizer {

	public static final String TAG = UsersSynchronizer.class.getSimpleName();

	private UsersLDAO usersLDAO;
	private UsersDataWriter usersDataWriter;
	private Map<String, User> userCache;

	private User currentUser;

	public UsersSynchronizer(Context context, User currentUser) {

		this.currentUser = currentUser;
		usersLDAO = new UsersLDAO(context);
		usersDataWriter = new UsersDataWriter(context);

	}

	/**
	 * Loads the user cache if it is not loaded yet.
	 */
	protected void lazyLoadUserCache() {
		if (userCache == null) {
			loadUserCache();
		}
	}

	/**
	 * Queries the database for all the users under the same company as the current user
	 * and places it to the user cache (userCache).
	 */
	protected void loadUserCache() {

		try {
			usersLDAO.open();
			List<User> users = usersLDAO.getCompanyUsers(currentUser.getCompany().getId());

			userCache = new HashMap<String, User>();

			for (User user : users) {
				userCache.put(user.getWebId(), user);
			}

		} finally {
			usersLDAO.close();
		}

	}

	/**
	 * Updates the user in the database if there are changes to it. Otherwise, this will
	 * just return the user from the database with updates. In case that the user is not
	 * yet registered, this method will register the user and return its data.
	 * 
	 * @param user
	 *            The user to update
	 * @param updateOptions
	 *            Determines how the user is updated in the database
	 * @return The data of the user from the database (including database id)
	 */
	public User updateUser(User user, EnumSet<UserUpdateOptions> updateOptions) {
		lazyLoadUserCache();

		String webId = user.getWebId();

		// Find the user in the cache, if it is already cached and it's values are equal
		// to the cached user instance, return that instance and do not do any updates.
		if (userCache.containsKey(webId)) {
			User cachedUser = userCache.get(webId);

			if (cachedUser.equals(user)) {
				return cachedUser;
			}
		}

		// The user is either not yet registered or needs an update
		return usersDataWriter.registerOrUpdateUser(user, updateOptions);

	}

}
